﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Microsoft.SharePoint;
using Kiiro.Common.Entities;
using Kiiro.Common.Utility;
using Kiiro.ExceptionManagement;
using FieldNames = Kiiro.Common.Utility.Constants.ActivityHistoryFieldNames;
using SPListNames = Kiiro.Common.Utility.Constants.SPListNames;

namespace Kiiro.DataAccess
{
    public class ActivityHistoryDA
    {
        #region Singleton
        private ActivityHistoryDA ( )
        {
        }

        private static ActivityHistoryDA instance = null;
        private static readonly object threadLock = new object ( );

        public static ActivityHistoryDA Instance
        {
            get
            {
                lock ( threadLock )
                {
                    if ( instance == null )
                    {
                        instance = new ActivityHistoryDA ( );
                    }
                }
                return instance;
            }
        }
        #endregion

        const string EqCaml = "<Eq><FieldRef Name='{0}'/><Value Type='{1}'>{2}</Value></Eq>";
        const string Text = "Text";
        const string Integer = "Integer";

        public List<ActivityHistory> GetActivity (
            Guid siteCollectionId, string serverRelativeUrl, ItemType itemType, int max, int userId )
        {
            List<ActivityHistory> histories = new List<ActivityHistory> ( );

            try
            {
                SPSiteDataQuery siteDQ = new SPSiteDataQuery ( );
                siteDQ.Webs = "<Webs Scope='Recursive'/>";
                siteDQ.Lists = "<Lists ServerTemplate='50000'/>";

                foreach ( string fieldName in FieldNames.AllFieldNames )
                    siteDQ.ViewFields += string.Format ( "<FieldRef Name='{0}'/>", fieldName );

                siteDQ.Query = GenerateWhereClause ( itemType, userId );

                DataTable dataTable;
                using ( SPWeb web = SPHelpers.GetWeb ( siteCollectionId, serverRelativeUrl ) )
                {
                    dataTable = web.GetSiteData ( siteDQ );
                }

                if ( dataTable != null && dataTable.Rows.Count > 0 )
                {
                    foreach ( DataRow dataRow in dataTable.Rows )
                    {
                        ActivityHistory activity = SPDataHelpers.MakeActivityHistory ( dataRow );
                        if ( activity.ReferencedItem != null )
                        {
                            histories.Add ( activity );
                            if ( histories.Count >= max )
                                break;
                        }
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, true );
            }

            return histories;
        }



        private string GenerateWhereClause ( ItemType itemType, int userId )
        {
            StringBuilder itemQuery = new StringBuilder ( );
            StringBuilder userQuery = new StringBuilder ( );
            StringBuilder whereClause = new StringBuilder ( );

            if ( itemType != ItemType.All )
            {
                if ( itemType == ItemType.Issue || itemType == ItemType.Task )
                {
                    itemQuery.Append ( string.Format( "<Or>{0}{1}</Or>",
                        string.Format ( EqCaml, FieldNames.ActivityItemType, Text, ItemType.Task ),
                        string.Format ( EqCaml, FieldNames.ActivityItemType, Text, ItemType.Issue ) ) );
                }
                else if ( itemType == ItemType.Discussion )
                {
                    itemQuery.Append ( string.Format( "<Or>{0}{1}</Or>",
                        string.Format ( EqCaml, FieldNames.ActivityItemType, Text, ItemType.Comment ),
                        string.Format ( EqCaml, FieldNames.ActivityItemType, Text, ItemType.Discussion ) ) );
                }
                else
                {
                    itemQuery.Append ( string.Format ( EqCaml, FieldNames.ActivityItemType, Text, itemType ) );
                }
            }

            if ( userId > 0 )
            {
                userQuery.Append ( string.Format ( EqCaml, FieldNames.CreatedBy, Integer, userId ) );
            }

            if ( itemQuery.Length > 0 || userQuery.Length > 0 )
            {
                whereClause.Append ( "<Where>" );

                if ( itemQuery.Length > 0 && userQuery.Length > 0 )
                    whereClause.Append ( "<And>" );

                whereClause.Append ( itemQuery.ToString ( ) );
                whereClause.Append ( userQuery.ToString ( ) );

                if ( itemQuery.Length > 0 && userQuery.Length > 0 )
                    whereClause.Append ( "</And>" );

                whereClause.Append ( "</Where>" );
            }

            whereClause.Append ( "<OrderBy><FieldRef Ascending='False' Name='" + FieldNames.ModifiedDate + "'/></OrderBy>" );

            return whereClause.ToString ( );
        }




        public void Save ( ActivityHistory activityHistory, Guid siteCollectionId, string serverRelativeUrl )
        {
            SPWeb web = null;

            try
            {
                if ( activityHistory.EditType != EditType.Unchanged )
                {
                    using ( web = SPHelpers.GetWeb ( siteCollectionId, serverRelativeUrl ) )
                    {
                        SPList list = web.Lists [ Constants.SPListNames.ActivityHistory ];

                        if ( list != null )
                        {
                            #region Get Item

                            SPListItem listItem = activityHistory.EditType == EditType.Created ? list.Folders.Add ( ) : list.Folders.GetItemById ( activityHistory.Id );

                            switch ( activityHistory.EditType )
                            {
                                case EditType.Created:
                                    list.ParentWeb.AllowUnsafeUpdates = true;
                                    listItem.Update ( );
                                    list.ParentWeb.AllowUnsafeUpdates = false;

                                    listItem = list.Folders.GetItemById ( listItem.ID );

                                    listItem [ Constants.ActivityHistoryFieldNames.ServerRelativeUrl ] = listItem.Folder.ServerRelativeUrl;
                                    listItem [ Constants.ActivityHistoryFieldNames.SiteCollectionId ] = list.ParentWeb.Site.ID;

                                    if ( activityHistory.CreatedBy != null && activityHistory.CreatedBy.Id > 0 )
                                        listItem [ Constants.ActivityHistoryFieldNames.CreatedBy ] = activityHistory.CreatedBy.Id;
                                    if ( activityHistory.CreatedDate != null && activityHistory.CreatedDate != DateTime.MinValue )
                                        listItem [ Constants.ActivityHistoryFieldNames.CreatedDate ] = activityHistory.CreatedDate;
                                    if ( activityHistory.ModifiedBy != null && activityHistory.ModifiedBy.Id > 0 )
                                        listItem [ Constants.ActivityHistoryFieldNames.ModifiedBy ] = activityHistory.ModifiedBy.Id;
                                    if ( activityHistory.ModifiedDate != null && activityHistory.ModifiedDate != DateTime.MinValue )
                                        listItem [ Constants.ActivityHistoryFieldNames.ModifiedDate ] = activityHistory.ModifiedDate;

                                    break;

                                case EditType.Updated:
                                    if ( activityHistory.ModifiedBy != null && activityHistory.ModifiedBy.Id > 0 )
                                        listItem [ Constants.ActivityHistoryFieldNames.ModifiedBy ] = activityHistory.ModifiedBy.Id;
                                    if ( activityHistory.ModifiedDate != null && activityHistory.ModifiedDate != DateTime.MinValue )
                                        listItem [ Constants.ActivityHistoryFieldNames.ModifiedDate ] = activityHistory.ModifiedDate;
                                    if (activityHistory.CreatedDate != null && activityHistory.CreatedDate != DateTime.MinValue)
                                        listItem[Constants.ActivityHistoryFieldNames.CreatedDate] = activityHistory.CreatedDate;
                                        break;

                                case EditType.Deleted:
                                default:
                                    break;
                            }
                            #endregion

                            #region Set Item Properties

                            if ( listItem != null && activityHistory.EditType != EditType.Deleted )
                            {
                                if ( !string.IsNullOrEmpty ( activityHistory.ActivityReferenceUrl ) )
                                    listItem [ Constants.ActivityHistoryFieldNames.ActivityReferenceUrl ] = activityHistory.ActivityReferenceUrl;

                                listItem [ Constants.ActivityHistoryFieldNames.ActivityItemType ] = activityHistory.ActivityItemType;
                                listItem [ Constants.ActivityHistoryFieldNames.EventType ] = activityHistory.EventType;

                                if ( !string.IsNullOrEmpty ( activityHistory.Title ) )
                                    listItem [ Constants.ActivityHistoryFieldNames.Title ] = activityHistory.Title.Trim ( );

                                if ( !string.IsNullOrEmpty ( activityHistory.Description ) )
                                    listItem [ Constants.ActivityHistoryFieldNames.Description ] = activityHistory.Description;
                            }
                            #endregion

                            #region Update / Delete Item
                            try
                            {
                                list.ParentWeb.AllowUnsafeUpdates = true;
                                if ( activityHistory.EditType == EditType.Deleted )
                                {
                                    list.Folders.DeleteItemById ( listItem.ID );
                                }
                                else
                                {
                                    listItem.Update ( );
                                    activityHistory = SPDataHelpers.MakeActivityHistory ( listItem );
                                }
                            }
                            catch ( Exception ex )
                            {
                                ExceptionManager.HandleException ( ex, true );
                            }
                            finally
                            {
                                list.ParentWeb.AllowUnsafeUpdates = false;
                            }
                            #endregion
                        }
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, true );
            }
            finally
            {
                if ( web != null )
                    web.Dispose ( );
            }
        }
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.DataAccess/ActivityHistoryDA.cs $
 * 
 * 17    2/08/10 5:04p Camerons
 * 
 * 16    1/25/10 1:17p Camerons
 * 
 * 15    1/12/10 12:02p Camerons
 * 
 * 14    1/11/10 12:40p Camerons
 * 
 * 13    12/14/09 2:10p Shafia
 * attachments file extensions validation for discussions, tasks, and
 * issues
 * 
 * 12    12/04/09 4:13p Shafia
 * 
 * 11    2/12/09 1:26p Shafia
 * 
 * 10    26/11/09 10:35a Camerons
 * 
 * 9     18/11/09 12:24p Camerons
 * 
 * 8     17/11/09 6:46p Camerons
 * 
 * 7     28/10/09 1:30a Tobys
 * Changed Save to also update CreatedDate so that this could be modified
 * after it's creation during an import from Basecamp.
 * 
 * 6     21/09/09 3:30p Camerons
 * First batch of changes for 1.1.x.x - Security groups update
 * 
 * 5     17/08/09 10:41a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/